const logger = require("../lib/logger");
const rpio = require("rpio");
const split = require("split");
const hardwarePWM = require("./hardwarePWM");

// 检查是否为树莓派环境
const isRealRaspberryPi = () => {
  try {
    const fs = require('fs');
    // 检查是否存在树莓派特定文件
    if (fs.existsSync('/proc/device-tree/model')) {
      const model = fs.readFileSync('/proc/device-tree/model', 'utf8');
      const isARMArch = process.arch === 'arm' || process.arch === 'arm64';
      const hasRaspberryPi = model.includes('Raspberry Pi');
      
      // 直接输出到stdout，确保可见
      console.log(`[GPIO] 环境检查: 设备型号=${model.trim()}, ARM架构=${isARMArch}, 树莓派=${hasRaspberryPi}`);
      
      return hasRaspberryPi && isARMArch;
    }
    return false;
  } catch (error) {
    console.log(`[GPIO] 环境检查失败: ${error.message}`);
    return false;
  }
};

// PWM控制策略：优先使用硬件PWM，在非树莓派环境下降级为模拟器
const USE_HARDWARE_PWM = isRealRaspberryPi();

console.log(`[GPIO] 🔧 PWM控制模式: ${USE_HARDWARE_PWM ? '硬件PWM' : 'PWM模拟器'}`);

if (USE_HARDWARE_PWM) {
  console.log('[GPIO] ✅ 使用硬件PWM控制，获得最佳性能');
} else {
  console.log('[GPIO] ⚠️  非树莓派环境，使用PWM模拟器进行兼容');
}

// Initialize hardware PWM properly
if (USE_HARDWARE_PWM) {
  // Initialize GPIO pins for PWM
  try {
    // Setup pins 12 and 13 for output mode with proper PWM initialization
    const { execSync } = require('child_process');
    execSync('sudo gpio -g mode 12 out', { stdio: 'ignore' });
    execSync('sudo gpio -g mode 13 out', { stdio: 'ignore' });
    // 初始化PWM模式
    execSync('sudo gpio -g pwm 12 0', { stdio: 'ignore' });
    execSync('sudo gpio -g pwm 13 0', { stdio: 'ignore' });
    console.log('[GPIO] ✅ GPIO引脚12和13初始化为PWM输出模式');
  } catch (error) {
    console.error(`[GPIO] ❌ GPIO引脚初始化失败: ${error.message}`);
  }
}

// 创建PWM模拟器（用于非树莓派环境）
const createPWMEmulator = () => {
  return {
    host_is_model_pi4: () => {
      console.log('[GPIO] PWM模拟器: 模拟host_is_model_pi4调用');
      return false;
    },
    create_dma_channel: (channel, config) => {
      console.log(`[GPIO] PWM模拟器: 模拟创建DMA通道 ${channel}`);
      return {
        create_pwm: (pin) => {
          console.log(`[GPIO] PWM模拟器: 模拟创建PWM引脚 ${pin}`);
          return {
            pin: pin,
            value: 0,
            set_width: (width) => {
              console.log(`[GPIO] PWM模拟器: 引脚${pin}设置宽度${width}`);
            },
            release: () => {
              console.log(`[GPIO] PWM模拟器: 释放引脚${pin}`);
            }
          };
        }
      };
    }
  };
};

let pwm = null;
let pwmCh = null;

// 仅在非硬件PWM模式下初始化模拟器
if (!USE_HARDWARE_PWM) {
  pwm = createPWMEmulator();
}

rpio.init({ mapping: "gpio" });

const status = {};

let refresh = 50, // 频率
  stepNum = 1000, // 精度
  pwmPinMap = {},
  switchPinList = [];

const cycleTimeUs = (1000 / refresh) * 1000, // 周期时长 20000us
  stepTimeUs = cycleTimeUs / stepNum; // 单步时长  40us

// PWM初始化状态标记
let pwmInitFailed = false;
/**
 * 初始化PWM通道 (仅用于模拟器模式)
 * @param {Number} refresh PWM 频率
 * @returns undefined
 */

const initPwmCh = () => {
  if (pwmCh) return;
  if (pwmInitFailed) {
    console.log('[GPIO] PWM初始化已失败，跳过重试');
    return;
  }

  if (!USE_HARDWARE_PWM) {
    console.log("[GPIO] 初始化 PWM 模拟器通道");

    try {
      const steeringPWMCfg = {
        cycle_time_us: cycleTimeUs,
        step_time_us: stepTimeUs,
        delay_hw: 1,
      };

      let dmaChannel = 12;
      try {
        dmaChannel = pwm.host_is_model_pi4() ? 5 : 12;
      } catch (hostCheckError) {
        console.log('[GPIO] 使用默认DMA通道 12');
      }

      pwmCh = pwm.create_dma_channel(dmaChannel, steeringPWMCfg);
      console.log("[GPIO] PWM 软件模拟器初始化成功");
    } catch (error) {
      console.error(`[GPIO] PWM 模拟器初始化失败: ${error.message}`);
      pwmInitFailed = true;
    }
  }
};

function initPin(pinBoardCode = 12) {
  if (pwmInitFailed) {
    console.log(`[GPIO] PWM初始化失败，跳过引脚 ${pinBoardCode} 初始化`);
    return null;
  }
  
  if (!pwmCh) {
    initPwmCh();
  }
  if (!pwmCh) {
    console.warn(`[GPIO] 无法创建PWM控制器，跳过引脚 ${pinBoardCode}`);
    return null;
  }
  try {
    return pwmCh.create_pwm(pinBoardCode);
  } catch (error) {
    console.error(`[GPIO] 创建PWM引脚 ${pinBoardCode} 失败: ${error.message}`);
    return null;
  }
}

function changePwmPin(pin, v) {
  pin = parseInt(pin);
  v = Number(v);
  console.log(`[GPIO] Change PWM channel: ${pin}, value: ${v}`);
  status[pin] = v;
  
  if (USE_HARDWARE_PWM) {
    // 使用硬件PWM控制
    hardwarePWM.setPWM(pin, v).catch(error => {
      console.error(`[GPIO] 硬件PWM控制引脚 ${pin} 错误: ${error.message}`);
    });
  } else {
    // 降级为模拟器控制（用于开发环境）
    if (!pwmPinMap[pin]) {
      pwmPinMap[pin] = initPin(pin);
    }
    
    if (!pwmPinMap[pin]) {
      console.warn(`[GPIO] PWM引脚 ${pin} 不可用，跳过控制`);
      return;
    }
    
    try {
      if (v == 0) {
        setRound(pwmPinMap[pin], 7.5);
      } else {
        setRound(pwmPinMap[pin], v * 2.5 + 7.5);
      }
    } catch (error) {
      console.error(`[GPIO] PWM控制引脚 ${pin} 错误: ${error.message}`);
    }
  }
}

/**
 * 设置空占比 (仅用于模拟器模式)
 * @param {Number} pin
 * @param {Number} round 空占比 0 ～ 100
 */
function setRound(pin, round) {
  pin.set_width((round / 100) * stepNum);
}

function readPin(pin) {
  pinBoardCode = parseInt(pinBoardCode);
  rpio.setup(pinBoardCode, rpio.INPUT);
  rpio.read(pinBoardCode, function (err, value) {
    if (err) {
      console.error(`[GPIO] Read pin ${pinBoardCode} error: ${err}`);
    } else {
      process.stdout.write(
        "gpio-change|" + JSON.stringify({ pin: pinBoardCode, value })
      );
    }
  });
}

function changeSwitchPin(pinBoardCode, enabled) {
  pinBoardCode = parseInt(pinBoardCode);
  enabled = JSON.parse(enabled);
  console.log(`[GPIO] Change Switch channel: ${pinBoardCode}, value: ${enabled}`);
  status[pinBoardCode] = enabled;
  // process.stdout.write(JSON.stringify(status));
  if (!switchPinList.includes(pinBoardCode)) {
    switchPinList.push(pinBoardCode);
  }
  if (enabled) {
    rpio.open(pinBoardCode, rpio.OUTPUT, rpio.HIGH);
  } else {
    rpio.open(pinBoardCode, rpio.OUTPUT, rpio.LOW);
  }
}

const closeChannel = function () {
  console.log("[GPIO] Close GPIO channel");
  
  if (USE_HARDWARE_PWM) {
    // 清理硬件PWM
    hardwarePWM.stopAllPWM().catch(error => {
      console.warn(`[GPIO] 清理硬件PWM失败: ${error.message}`);
    });
  } else {
    // 清理模拟器PWM
    Object.keys(pwmPinMap).forEach((pin) => {
      try {
        changePwmPin(pin, 0);
        if (pwmPinMap[pin] && pwmPinMap[pin].release) {
          pwmPinMap[pin].release();
        }
      } catch (error) {
        console.warn(`[GPIO] 关闭PWM引脚 ${pin} 时出错: ${error.message}`);
      }
    });
  }

  switchPinList.forEach((pin) => {
    try {
      changeSwitchPin(pin, false);
      rpio.close(pin);
    } catch (error) {
      console.warn(`[GPIO] 关闭开关引脚 ${pin} 时出错: ${error.message}`);
    }
  });
  
  pwmPinMap = {};
  switchPinList = [];
};

rpio.on("change", (pin, value) => {
  console.log(`[GPIO] GPIO ${pin} changed to ${value}`);
  process.stdout.write("gpio-change|" + JSON.stringify({ pin, value }));
});

process.stdin.pipe(split()).on("data", (data) => {
  console.log(`[GPIO] Receive data: ${data}\n`);
  const [type, pin, v] = data.toString().split(" ");
  try {
    switch (type) {
      case "listen":
        listen(pin);
      case "pwm":
        changePwmPin(pin, v);
        break;
      case "sw":
        changeSwitchPin(pin, v);
        break;
      case "close":
        closeChannel();
        break;
      case "exit":
        process.exit(0);
      default:
        break;
    }
  } catch (error) {
    console.error(`[GPIO] Error: ${error}`);
    process.stderr.write(error.toString());
  }
});

// 添加进程消息监听器，用于接收父进程的消息
process.on('message', (message) => {
  if (message && message.type === 'log') {
    console.log(`[GPIO Parent] ${message.message}`);
  }
});

process.on("exit", () => {
  closeChannel();
  console.log("[GPIO] gpio server exit");
});

process.on("disconnect", () => {
  console.log("[GPIO] gpio server disconnect");
  process.exit(0);
});